import QtQuick 2.0
import FileIO 1.0
import Async 1.0

Item {
    id: integrityCheck

    readonly property string pkgVersionFilePath: settings.gamePath + "pkg_version"

    signal finished()

    property var progress: ({})


    property var files: []
    property var checked: ({})

    property int okCount: 0
    property int errorCount: 0
    property int ignoredCount: 0

    property bool isWinePatchInstalled: false
    readonly property var filesToIgnore: !isWinePatchInstalled ? []
        : ["crashreport.exe", "upload_crash.exe", "UnityPlayer.dll", "xlua.dll"]

    Async {
        id: async

        onFinished: {
            ui.log(qsTr("Integrity check finished."))
            ui.log(qsTr("Files OK: ") + okCount + qsTr(", Errors: ") + errorCount + qsTr(", Ignored: ") + ignoredCount)
            integrityCheck.finished()
        }

        onResult: {
            progress = {
                value: okCount + errorCount + ignoredCount + 1,
                total: files.length
            }

            let filePath = values[0]
            let fileName = filePath.replace(/^.*\//, "")
            let fileMd5 = values[1]
            if (!fileMd5) {
                if (filesToIgnore.indexOf(fileName) !== -1) {
                    ++ignoredCount
                } else {
                    ++errorCount
                    ui.log("⚠️ MISSING: " + filePath)
                }
                return
            }

            let pkg = checked[filePath]
            if (!pkg) {
                ++errorCount
                ui.log("⚠️ Unknown File" + filePath)
                return
            }

            fileMd5 = fileMd5.toLowerCase()
            let pkgMd5 = pkg.md5.toLowerCase()
            if (fileMd5 !== pkgMd5) {
                if (filesToIgnore.indexOf(fileName) !== -1) {
                    ++ignoredCount
                } else {
                    ui.log(qsTr("⚠️ WRONG MD5: ") + fileMd5 + qsTr(" vs ") + pkgMd5 + ": " + pkg.remoteName)
                    ++errorCount
                }
            } else {
                ++okCount
            }
        }
    }

    function reload() {
        let pkgs = FileIO.readTextFile(pkgVersionFilePath).split("\n")

        let files = []
        for (let pkg of pkgs) {
            if (pkg.trim() === "")
                continue

            try {
                let json = JSON.parse(pkg)
                files.push(json)
            } catch(e) {
                ui.log(file + ": " + e)
            }
        }
        integrityCheck.files = files
    }

    function stop() {
        async.stop()
    }

    function checkAll() {
        isWinePatchInstalled = FileIO.isFileExists(settings.gamePath + 'launcher.bat')

        okCount = 0
        errorCount = 0
        ignoredCount = 0
        ui.log("")
        ui.log(qsTr("Integrity check started. This may take time..."))
        checked = {}

        let result = true
        let fileNames = []
        for (let file of files) {
            let fileName = settings.gamePath + file.remoteName
            fileNames.push(fileName)
            checked[fileName] = file
        }

        async.md5List(fileNames)
    }

    function check(remoteName) {
        let pkg = getPkg(remoteName)
        let fileSize = FileIO.size(settings.gamePath + remoteName)
        if (fileSize !== pkg.fileSize) {
            ui.log(qsTr("File size doesn't match: ")
                    + fileSize + qsTr(" vs ") + pkg.fileSize + ": " + remoteName)
            return false
        }

        let md5 = FileIO.md5(settings.gamePath + remoteName).toLowerCase()
        let pkgMd5 = pkg.md5.toLowerCase()
        if (md5 !== pkgMd5) {
            ui.log(qsTr("File md5 doesn't match: ")
                    + md5 + qsTr(" vs ") + pkgMd5 + ": " + remoteName)
            return false
        }

        ui.log(remoteName + qsTr(" integrity ok"))
        return true
    }

    function getPkg(remoteName) {
        for (let file of files) {
            if (file.remoteName === remoteName) {
                return file
            }
        }
    }
}
